﻿#include "downloaddialog.h"
#include "ui_downloaddialog.h"

#include <QProcess>
#include <QFileInfo>
#include <QDebug>
#include <QMessageBox>
#include <QDir>
#include <QUrl>
#include <QFileDialog>
#include <QFile>
#include <QStandardItemModel>
#include <QThread>
#include <QStringList>

#include <thread>

#include <log/msghandlerwapper.h>

#if WIN32
const QString WorkPath("Z:/download");
const QString AxelPath("D:/install/msys64/usr/bin/axel.exe");
#else
const QString WorkPath("/dev/shm/download");
const QString AxelPath("/usr/bin/axel");
#endif


DownloadDialog::DownloadDialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::DownloadDialog)
{
    ui->setupUi(this);
    m_Stop = false;
    m_ThreadS = 0;

    connect(MsgHandlerWapper::instance(), &MsgHandlerWapper::LogMessageSig,
        [this](const QtMsgType, const QString, const QString &msg)
            {
              ui->LogWindow->append(msg);
            });

    QDir::setCurrent(WorkPath);
    ui->WgetPath->setText(AxelPath);
    ui->CurrentPathInput->setText(WorkPath);
}

DownloadDialog::~DownloadDialog()
{
    delete ui;
}

bool DownloadDialog::InitPath(QString path)
{
    QString IndexStr = "";
    if(path.isEmpty())
    {
        IndexStr = ui->IndexPath->text();
    }
    else
    {
        IndexStr = path;
    }

    if(IndexStr.isEmpty())
    {
        qInfo() << u8"路径不存在!";
        return false;
    }

    QUrl paraUrl(IndexStr);
    if(paraUrl.isValid())
    {
        m_FileName = paraUrl.fileName();
        m_BasePath = paraUrl.url(QUrl::RemoveFilename);
    }
    else
    {
        return false;
    }
    return true;
}

bool DownloadDialog::CleanDir( QString tmpName,
                               QStringList TmpFileSub)
{
    QFile TestFile(tmpName + ".st");
    if(TestFile.exists())
    {
        if( !TestFile.remove() )
        {
            qDebug() << "Delete file error:" << TestFile.fileName();
            return false;
        }
        qDebug() << u8"删除文件:" << TestFile.fileName();

        TestFile.setFileName(tmpName);
        if( !TestFile.remove() )
        {
            qDebug() << "Delete file error:" << TestFile.fileName();
            return false;
        }
        qDebug() << u8"删除文件:" << TestFile.fileName();
    }

    for(auto item : TmpFileSub)
    {
        TestFile.setFileName(tmpName + item);
        if(TestFile.exists())
        {
            if( !TestFile.remove() )
            {
                qDebug() << "Delete file error:" << TestFile.fileName();
                return false;
            }
            qDebug() << u8"删除文件:" << TestFile.fileName();
            continue;
        }
    }

    return true;
}

bool DownloadDialog::InitList(QString IndexUrl)
{
    if(IndexUrl.isEmpty())
    {
        QString LogStr(u8"路径不存在!");
        qInfo() << LogStr;
        return false;
    }
    InitPath(IndexUrl);

    QFile LocalFile(m_FileName);
    if(!LocalFile.exists()) //本地文件不存在则下载
    {        
       if( !DownloadFile(IndexUrl))
       {
           return false;
       }
    }
    else
    {
        qInfo() << u8"利用本地文件:" << m_FileName;
    }

    if( !LocalFile.open(QIODevice::ReadOnly) )
    {
        return false;
    }

    if(m_pDownloadOver)
    {
        m_pDownloadOver->clear();
    }
    else
    {
        m_pDownloadOver = new QStandardItemModel(this);
    }

    if(m_pWaiteDownload)
    {
        m_pWaiteDownload->clear();
    }
    else
    {
        m_pWaiteDownload = new QStandardItemModel(this);
    }

    //尝试初始化列表
    QTextStream in(&LocalFile);
    while (!in.atEnd())
    {
        QString line = in.readLine();
        if(line.startsWith('#'))
        {
            continue;
        }
        else
        {
            QString LocalFileName;
            QString  UrlName;
            QUrl IsUrl(line);  //判断是不是url
            if( IsUrl.isRelative() )
            {
                //qDebug() << u8"相对url路径！";
                LocalFileName = line;
                UrlName = m_BasePath + "/" + line;
            }
            else if(IsUrl.isValid())
            {
                //qDebug() << u8"合法url路径！";
                LocalFileName = IsUrl.fileName();
                UrlName = line;
            }
            else
            {
                LocalFileName = line;
                UrlName = m_BasePath + "/" + line;
            }

            QFile CheckFile(QFileInfo(LocalFileName).fileName());
            CleanDir( CheckFile.fileName());

            if(CheckFile.exists())
            {
                m_pDownloadOver->appendRow(new QStandardItem(UrlName));
                continue;
            }
            else
            {
                m_pWaiteDownload->appendRow(new QStandardItem(UrlName));
                continue;
            }
        }
    }

    for(int ind=0; ind<m_pDownloadOver->rowCount(); ind++)
    {
        m_pDownloadOver->setData(m_pDownloadOver->index(ind, 0), QBrush(Qt::green), Qt::ForegroundRole);
    }

    for(int ind=0; ind<m_pWaiteDownload->rowCount(); ind++)
    {
        m_pWaiteDownload->setData(m_pWaiteDownload->index(ind, 0), QBrush(Qt::red), Qt::ForegroundRole);
    }

    ui->DownloadOverView->setModel(m_pDownloadOver);
    ui->WaiteDownloadView->setModel(m_pWaiteDownload);

    return false;
}

bool DownloadDialog::DownloadFile(QString FileUrl)
{
    QString program = ui->WgetPath->text();
    QFileInfo info(program);
    if(!info.exists() && !info.isExecutable())
    {
        QString LogStr(u8"wget不存在!");
        qInfo() << LogStr;
        QMessageBox::warning(0, QString(u8"错误"), LogStr, QMessageBox::Yes, QMessageBox::Yes);
        return false;
    }

    QStringList arguments;
    //arguments << "-d";
    arguments << FileUrl;//传递到exe的参数

    QProcess myProcess(0);
    myProcess.start(program, arguments);
    if( !myProcess.waitForStarted() )
    {
        qDebug() << "myProcess error:" << program << arguments;
        return false;
    }

    QByteArray AllData;
    while (myProcess.waitForFinished(10*60*1000) == false) {
        QByteArray qByteRead = myProcess.readAllStandardOutput();
        if (!qByteRead.isEmpty()) {
            AllData.append(qByteRead);
        }
        qDebug() << "下载超时："<<FileUrl;
        return false;
    }
    qDebug() << "下载完成:"<<FileUrl;
    QByteArray qByteRead = myProcess.readAllStandardOutput();
    AllData.append(qByteRead);

    qDebug() << AllData.toStdString().c_str();
    return true;
}

bool DownloadDialog::GetTask(QString& FileName)
{
    std::lock_guard<std::mutex> guard(m_Mutex);
    FileName = m_pWaiteDownload->data(m_pWaiteDownload->index(0, 0)).toString();
    m_pDownloadOver->appendRow(new QStandardItem(FileName));

    if( !ui->WaiteDownloadView->model()->removeRow(0))
    {
        return false;
    }
    return true;
}

bool DownloadDialog::DownloadFileList()
{
    QString NewFileName;
    m_ThreadS += 1;

    m_Stop = false;
    while(GetTask( NewFileName ))
    {
        if(m_Stop)
        {
            m_ThreadS -= 1;
            qDebug() <<QThread::currentThread()<<":stop, Running:"<<m_ThreadS;
            return false;
        }

        if(NewFileName.isEmpty())
        {
            qDebug() <<QThread::currentThread()<<":Download failed: File name isEmpty!";
            return false;
        }

        qDebug() <<QThread::currentThread()<<": Download :"<<NewFileName;
        if( !DownloadFile( NewFileName) )
        {
            m_ThreadS -= 1;
            qDebug() <<QThread::currentThread()<<":error end, Running:"<<m_ThreadS;
            return false;
        }

        if(m_Stop)
        {
            m_ThreadS -= 1;
            qDebug() <<QThread::currentThread()<<":stop, Running:"<<m_ThreadS;
            return false;
        }
    }

    m_ThreadS -= 1;
    qDebug() <<QThread::currentThread()<<":download over, Running:"<<m_ThreadS;
    return true;
}

void DownloadDialog::on_BtnSetIndexPath_clicked()
{
    QString IndexPath = ui->IndexPath->text();
    InitList(IndexPath);
}

void DownloadDialog::on_btnSetCurrentPath_clicked()
{
    QString path = QFileDialog::getExistingDirectory(this, "/dev/shm/dir");
    ui->CurrentPathInput->setText(path);
    if( QDir::setCurrent(path) ) // 需要设置的运行时默认工作路径
    {
        qDebug() << "Set work path:" << path <<" ok!";
    }
    else
    {
        qInfo() << "Set work path:" << path <<" failed!";
    }
}

void DownloadDialog::on_BtnParaFile_clicked()
{
    if(!m_Timer)
    {
        m_Timer = new QTimer(this);
        connect(m_Timer, SIGNAL(timeout()), this, SLOT(UpdateTimes()));
        m_Timer->start(1000);
    }
    std::thread runThread([this]()
    {
        DownloadFileList();
    });
    runThread.detach();
}

void DownloadDialog::UpdateTimes()
{
    ui->SetThreadSpinBox->setValue(m_ThreadS);
    ui->labelDownloadOver->setText(QString(u8"已下载：%1").arg(m_pDownloadOver->rowCount()));
    ui->labelWaiteDownload->setText(QString(u8"待下载：%1").arg(m_pWaiteDownload->rowCount()));
}

void DownloadDialog::on_btnSetWgetPath_clicked()
{

}

void DownloadDialog::on_btnStop_clicked()
{
    m_Stop = true;
}

void DownloadDialog::on_BtnMergerToFile_clicked()
{
    QString SaveName = QFileDialog::getSaveFileName();
    if(SaveName.isEmpty())
    {
        return ;
    }

    QString program  = "D:/Libs/SVG/ImageMagick-7.0.10-1_vs/x64/bin/ffmpeg.exe";
    MergerFile(program, SaveName);
}

bool DownloadDialog::MergerFile(QString program, QString outName, int timeOut)
{
    QFileInfo info(program);
    if(!info.exists() && !info.isExecutable())
    {
        QString LogStr(u8"wget不存在!");
        qInfo() << LogStr;
        QMessageBox::warning(0, QString(u8"错误"), LogStr, QMessageBox::Yes, QMessageBox::Yes);
        return false;
    }

    //ffmpeg -i "concat:file001.ts|file002.ts|file003.ts|file004.ts......n.ts" -acodec copy -vcodec copy -absf aac_adtstoasc out.mp4
    //ffmpeg -i https://ip182.com/media=hlsA/ssd2/21/8/184547828.m3u8 -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4
    //ffmpeg -i https://ip182.com/media=hlsA/ssd2/21/8/184547828.m3u8 -acodec copy  output.mp4
    QStringList arguments;
    arguments << QString("-i %1").arg(m_FileName);//传递到exe的参数
    arguments << "-acodec copy";
    arguments << "-vcodec copy";
    arguments << outName;

    QProcess myProcess(0);
    myProcess.start(program, arguments);
    if( !myProcess.waitForStarted() )
    {
        qDebug() << "myProcess error:" << program << arguments;
        return false;
    }

    QByteArray AllData;
    while (myProcess.waitForFinished(timeOut) == false) {
        QByteArray qByteRead = myProcess.readAllStandardOutput();
        if (!qByteRead.isEmpty()) {
            AllData.append(qByteRead);
        }
        qDebug() << "合并超时："<<m_FileName;
        return false;
    }
    qDebug() << "合并完成:"<<m_FileName;
    QByteArray qByteRead = myProcess.readAllStandardOutput();
    AllData.append(qByteRead);

    qDebug() << AllData.toStdString().c_str();
    return true;
}

